package com.tceasy.gateway.api;

import com.tceasy.common.utils.date.DateUtils;
import com.tceasy.common.utils.json.JsonUtil;
import com.tceasy.gateway.dao.DeveloperDao;
import com.tceasy.gateway.domain.OpenDeveloper;
import com.tceasy.gateway.util.SignUtil;
import com.tceasy.gateway.util.SpringUtils;
import org.apache.commons.httpclient.util.DateParseException;
import org.apache.commons.httpclient.util.DateUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.util.Assert;
import org.springframework.util.PropertyPlaceholderHelper;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.*;

/**
 *Created by zhanghuan on 2016/4/10.
 */
@Configurable(autowire = Autowire.BY_NAME)
public class RequestParamUtil {
    static final Logger logger= LoggerFactory.getLogger(RequestParamUtil.class);

    static DeveloperDao developerDao;

    private static final long maxTimeDiff=10*1000;/*时间误差不能大于10s*/

    /** Default placeholder prefix: {@value} */
    public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

    /** Default placeholder suffix: {@value} */
    public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

    /** Default value separator: {@value} */
    public static final String DEFAULT_VALUE_SEPARATOR = ":";

    public static boolean ignoreUnresolvablePlaceholders = true;

    public static PropertyPlaceholderHelper placeholderHelper;

    static{
        RequestParamUtil.placeholderHelper=new PropertyPlaceholderHelper(DEFAULT_PLACEHOLDER_PREFIX,DEFAULT_PLACEHOLDER_SUFFIX,DEFAULT_VALUE_SEPARATOR,ignoreUnresolvablePlaceholders);
        RequestParamUtil.developerDao = SpringUtils.getBean(DeveloperDao.class);
    }

    /**解析参数*/
    public static String getParam(HttpServletRequest httpRequest){
        try {
            /*获取zipParams参数*/
            String charset= httpRequest.getCharacterEncoding();
            ServletInputStream inputStream = httpRequest.getInputStream();
            String param = IOUtils.toString(inputStream,charset);
            inputStream.close();
            return param;
        } catch (IOException e) {
            logger.error("解析客户端参数异常",e);
            throw new RuntimeException("解析客户端参数异常");
        }
    }

    /**
     * 解析并校验参数,对参数验签，权限过滤等等
     * @param param
     * @return
     */
    public static Map parseParam(String param){
        Map json = JsonUtil.toMap(param);
        if(json==null){
            throw new RuntimeException("参数格式错误");
        }
        String verifyIgnore= (String) json.get("verifyIgnore");
        String partner= (String) json.get("partner");
        String service = (String) json.get("service");
        Assert.hasText(partner,"合作账号不能为空");
        Assert.hasText(service,"接口名称不能为空");
        Assert.hasText((String) json.get("charset"),"charset不能为空");
        Assert.hasText((String) json.get("version"),"version不能为空");
        /*验签后门，如果指定了verifyIgnore=true，则忽略验签*/
        if(StringUtils.equals(verifyIgnore,"true")){
            return json;
        }
        String signType= (String) json.get("signType");
        String timestamp = (String) json.get("timestamp");
        Assert.hasText(timestamp,"timestamp不能为空");
        Assert.hasText(signType,"signType不能为空");
        Assert.hasText((String) json.get("sign"),"sign不能为空");
        Date requestDate= null;
        try {
            requestDate = DateUtil.parseDate(timestamp, Arrays.asList("yyyy-MM-dd HH:mm:ss"));
        } catch (DateParseException e) {
            throw new RuntimeException("时间戳格式错误");
        }
        long timeDIFF= System.currentTimeMillis()-requestDate.getTime();
        Assert.isTrue(timeDIFF<maxTimeDiff,"请求误差时间太大");
        OpenDeveloper merchant= developerDao.getByPartner(partner);
        if(signType.equalsIgnoreCase("md5")){
            SignUtil.verifyMd5Sign(json, merchant.getKey());
        }else if(signType.equalsIgnoreCase("rsa")){
            SignUtil.verifyRSASign(json,merchant.getPublicKey());
        }else{
            throw new RuntimeException("signType参数错误");
        }
        return json;
    }


    /**
     * 解析带占位符的字符串
     * @param strVal
     * @param context
     * @return
     */
    public static String replacePlaceholders(String strVal,final Map<String,String> context) {
        if(StringUtils.isBlank(strVal)){
            return "";
        }
        Assert.isTrue(context != null && context.size() > 0, "占位符所需要的元数据不能为空");
        PropertyPlaceholderHelper.PlaceholderResolver resolver = new PropertyPlaceholderConfigurerResolver(context);
        return placeholderHelper.replacePlaceholders(strVal, resolver);
    }

    public static void main(String[] args) {
        String strVal="name=${name}&json={id:${id},value:${value}}";
        String reg=strVal.replaceAll("\\$\\{*\\}","");

        Map contxt=new HashMap();
        contxt.put("name","zairian");
        contxt.put("id","10");
        contxt.put("value","谢谢");
        System.out.println(RequestParamUtil.replacePlaceholders(strVal,contxt));
    }


    /*获取远端Ip*/
    public static String getRemoteIp(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (StringUtils.isBlank(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {

            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1")) {
                // 根据网卡取本机配置的IP
                ipAddress = getLocalIp();
            }
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) {
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /*根据网卡获取本地ip*/
    public static String getLocalIp(){
        try {
            InetAddress inetAddress= InetAddress.getLocalHost();
            if(inetAddress!=null){
                return inetAddress.getHostAddress();
            }
        } catch (UnknownHostException e) {
            logger.error(e.toString());
        }
        return null;
    }


    /**获取header*/
    public static String getHearders(HttpServletRequest request){
        Enumeration enumeration= request.getHeaderNames();
        StringBuilder sb=new StringBuilder();
        while(enumeration.hasMoreElements()){
            String heardName=enumeration.nextElement().toString();
            String value=request.getHeader(heardName);
            sb.append(heardName).append("=").append(value).append(";");
        }
        int index=sb.lastIndexOf(";");
        if (index>0){
            sb.deleteCharAt(index);
        }
        return sb.toString();
    }


    private static class PropertyPlaceholderConfigurerResolver implements PropertyPlaceholderHelper.PlaceholderResolver {

        private final Map<String,String> props;

        private PropertyPlaceholderConfigurerResolver(Map<String,String> props) {
            this.props = props;
        }

        public String resolvePlaceholder(String placeholderName) {
            return  props.get(placeholderName);
        }
    }

}
